//
//  DSConnect.m
//  MyClient
//
//  Created by lin on 16/3/22.
//  Copyright © 2016年 lin. All rights reserved.
//

#import "DSConnect.h"

#import "GCDAsyncSocket.h"

@interface DSConnect () <GCDAsyncSocketDelegate>

@end

@implementation DSConnect

+ (DSConnect *)sharedDSConnect
{
    static DSConnect *connect;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        connect = [[self alloc] init];
    });
    
    return connect;
}

- (void)start {
    netServiceBrowser = [[NSNetServiceBrowser alloc] init];
    
    [netServiceBrowser setDelegate:self];
    [netServiceBrowser searchForServicesOfType:@"_YourServiceName._tcp." inDomain:@"local."];
}

- (void)stop {
    [_asyncSocket disconnect];
}

- (void)reConnect {
    if (![self connectToNextAddress]) {
        netServiceBrowser = nil;
        serverService = nil;
        serverAddresses = nil;
        _asyncSocket = nil;
        [self start];
    }
}

#pragma mark -  NSNetServiceBrowser Delegate
- (void)netServiceBrowser:(NSNetServiceBrowser *)sender didNotSearch:(NSDictionary *)errorInfo
{
    NSLog(@"DidNotSearch: %@", errorInfo);
}

- (void)netServiceBrowser:(NSNetServiceBrowser *)sender
           didFindService:(NSNetService *)netService
               moreComing:(BOOL)moreServicesComing
{
    NSLog(@"DidFindService: %@", [netService name]);
    
    // Connect to the first service we find
    
    if (serverService == nil)
    {
        NSLog(@"Resolving...");
        
        serverService = netService;
        
        [serverService setDelegate:self];
        [serverService resolveWithTimeout:5.0];
    }
}

- (void)netServiceBrowser:(NSNetServiceBrowser *)sender
         didRemoveService:(NSNetService *)netService
               moreComing:(BOOL)moreServicesComing
{
    NSLog(@"DidRemoveService: %@", [netService name]);
    _connected = NO;
}

- (void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)sender
{
    NSLog(@"DidStopSearch");
}

- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict
{
    NSLog(@"DidNotResolve");
}

- (void)netServiceDidResolveAddress:(NSNetService *)sender
{
    NSLog(@"DidResolve: %@", [sender addresses]);
    
    if (serverAddresses == nil)
    {
        serverAddresses = [[sender addresses] mutableCopy];
    }
    
    if (_asyncSocket == nil)
    {
        _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
        
        [self connectToNextAddress];
    }
}

- (BOOL)connectToNextAddress
{
    BOOL done = NO;
    
    while (!done && ([serverAddresses count] > 0))
    {
        NSData *addr;
        
        // Note: The serverAddresses array probably contains both IPv4 and IPv6 addresses.
        //
        // If your server is also using GCDAsyncSocket then you don't have to worry about it,
        // as the socket automatically handles both protocols for you transparently.
        
        if (/* DISABLES CODE */ (YES)) // Iterate forwards
        {
            addr = [serverAddresses objectAtIndex:0];
            [serverAddresses removeObjectAtIndex:0];
        }
        else // Iterate backwards
        {
            addr = [serverAddresses lastObject];
            [serverAddresses removeLastObject];
        }
        
        NSLog(@"Attempting connection to %@", addr);
        
        NSError *err = nil;
        if ([_asyncSocket connectToAddress:addr error:&err])
        {
            done = YES;
        }
        else
        {
            NSLog(@"Unable to connect: %@", err);
        }
        
    }
    
    if (!done)
    {
        NSLog(@"Unable to connect to any resolved address");
    }
    
    return done;
}

#pragma mark - GCDAsyncSocket Delegate
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    NSLog(@"Socket:DidConnectToHost: %@ Port: %hu", host, port);
    
    _connected = YES;
    
    [self.delegate connectSuccess:self];
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    NSLog(@"SocketDidDisconnect:WithError: %@", err);
    
    if (!_connected)
    {
        [self connectToNextAddress];
    } else {
        [self reConnect];
    }
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSLog(@"Did Read Data:%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    [sock readDataWithTimeout:10.0f tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
    NSLog(@"Did Write Data With Tag:%@", @(tag));
}

@end
